iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
0
Modern Web

NestJs 讀書筆記系列 第 28

NestJs 延伸篇 - Federation 實作

  • 分享至 

  • xImage
  •  

上一篇我們建立了 gateway ,也把 Task Service 安裝了 federation 的 dependency
接著我們建立 User Service 和 Message Service,也都需要安裝 federation
之後在 User Service 寫一個 Create User 的 API

root
 ├── services
 │    ├── task     (port: 4002)
 │    ├── user     (port: 4001)
 │    └── message  (port: 4003)
 └── gateway       (port: 4000)

根據之前的情境
一個 Task 會由一個 User 所建立
一個 User 可以有多的 Task

Task 必須與 User 有所關聯,所以我們在 Task 中會新增一個 UserId 的欄位

User Service

使用 @key(fields: "_id") directive 設定 User 要接收什麼欄位,這邊以 _id 為例子

Code first

在 model 中使用 @Directive 設定

@Directive(`@key(fields: "_id")`)
export class User extends Document {
    @Field(() => ID)
    _id: string;
}

Schema first

type User @key(fields: "_id") {
  _id: ID!
  name: String!
}

在 resolver 中還有另一個方法 resolveReference ,當有相關的資源要使用 User 的實體時,Apollo Gateway 便能使用它
注意的是要在 resolveReference 加上 @ResolveReference decorator

@ResolveReference()
resolveReference(reference: { __typename: string; _id: string }) {
    return this.usersService.findById(reference._id);
}

Task Service

使用 extend 來標記 User

Code first

在 Task 中新增一個 user 的 model ,指定要 extend 的欄位

@Directive('@extends')
@Directive(`@key(fields: "_id")`)
@ObjectType()
export class User {
  @Directive('@external')
  @Field(() => ID)
  _id: string;
}

Schema first

extend type User @key(fields: "id") {
  id: ID! @external
}

Resolver

接著在 Resolver 中寫一個解析欄位物件的一個方法

@ResolveField(() => User)
user(@Parent() task: Task) {
  return { __typename: 'User', _id: task.userId };
}

以上我們就完成了在 gateway 中能利用 Task 的 userId ,到 User Service 中查詢 User 並回傳給 Task Service ,最終根據 Schema 的格式回傳給 Client side

測試

:::warning
在開始測試前,請讀者先將之前的資料先全部清除,之前的 Task 並沒有 userId 的欄位,所以無法查出 User 物件
:::

我們直接在 http://localhost:4000/graphql gateway 上做測試

先建立一個 User

mutation {
  createUser(userData: { name: "JavaScript" }) {
    _id
    name
  }
}

接著建立 Task
這邊與之前不一樣得部分是多了一個 userId ,如果剛剛的 User 回傳的 _id 沒有紀錄,請讀者到資料庫去找一下吧!
回傳時,我們也能取得 User 的物件

mutation {
  createTask(taskData: { 
    title: "THE THING TO DO TODAY",
    content: "THE THING Content"
    userId: "5f840e6de88fe979392f010c"
  }) {
    _id
    title
    content
    user {
      name
      _id
    }
  }
}

最後使用查詢找出剛剛建立的 Task

query {
  todoTasks {
    tasks {
      user {
        name
        _id
      }
      content
      title
    }
  }
}

完美!!!!/images/emoticon/emoticon07.gif


上一篇
NestJs 延伸篇 - Federation 設定
下一篇
NestJs 延伸篇 - Gateway 與 前端接通
系列文
NestJs 讀書筆記31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言